module dice.ui.container;

import dice.ui.gadget;
import dice.render.structs;
import dice.render.painter;
import dice.ui.layout;

/** A gadget that may contain other gadgets */
class Container : Gadget
{
	/* Layout */
	Layout _layout;
	
	/** Gets the container's layout */
	Layout layout ()
	{
		return _layout;
	}
	
	/** Sets the container's layout */
	void layout (Layout l)
	{
		_layout = l;
	}
	
	/** True if the container currently needs to invoke the layout manager */
	bool needsLayout;
	
	/** Invokes the layout engine if layout info is not up-to-date */
	void ensureLayout ()
	{
		if (needsLayout == false)
			return;
		
		needsLayout = false;
		if (layout !is null)
		{
			layout.layout(this);
		}
	}
	
	/* Contents */
	Gadget[] contents;
	
	/** Add a gadget */
	void add (Gadget g)
	{
		synchronized (this, g)
		{
			g.parent = this;
			
			contents = g ~ contents;
			
			needsLayout = true;
		}
	}
	
	/** Remove a gadget */
	void remove (Gadget g)
	{
		synchronized (this, g)
		{
			g.parent = null;
			
			Gadget[] c;
			foreach (Gadget i; contents)
				if (i != g)
					c = c ~ i;
			contents = c;
			
			needsLayout = true;
		}
	}
	
	/** Returns the rectangle in which contents may reside */
	Rect contentsRect ()
	{
		Rect r = rect;
		return Rect(r.x1+5, r.y1+5, r.x2-5, r.y2-5);
	}
	
	/* ChildAtMousePosition */
	/** Returns the child gadget at given mouse position */
	Gadget childAtMousePosition (float x, float y)
	{
		foreach (Gadget g; contents)
			if (g.containsMousePosition(x-g.rect.x1,y-g.rect.y1))
				return g;
		return null;
	}
	
	/* Drawing */
	/** Draws the contents of this container */
	void drawContents (Painter p)
	{
		foreach (Gadget g; contents)
		{
			p.save();
			
			p.matrix = Matrix(1,0,0,1, g.rect.x1, g.rect.y1);
			
			g.draw(p);
			
			p.restore();
		}
	}
	
	/* Re-draw */
	void redraw (Rect r)
	{
		if (hasParent)
		{
			Rect me = rect;
			parent.redraw(Rect(r.x1-me.x1,r.y1-me.y1,r.x2-me.x1,r.y2-me.y1));
		}
	}
	
	void redrawAll ()
	{
		redraw(Rect(0,0,rect.x2-rect.x1,rect.y2-rect.y1));
	}
} 
